package org.huzhp.gateway.filter;

import cn.hutool.http.useragent.UserAgent;
import cn.hutool.http.useragent.UserAgentUtil;
import org.huzhp.gateway.service.AbstractAuditLogService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.route.Route;
import org.springframework.cloud.gateway.support.ServerWebExchangeUtils;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @Description: 日志拦截器
 * @Author: huzp
 * @CreateDate: 2020/3/13 13:02
 * @Version: 1.0
 */
@Component
public class LogGatewayFilterFactory extends CommonGatewayFilterFactory<LogGatewayFilterFactory.Config> {

    @Autowired
    private AbstractAuditLogService auditLogService;

    private static final String START_TIME = "startTime";

    public LogGatewayFilterFactory() {
        super(Config.class);
    }

    @Override
    public List<String> shortcutFieldOrder() {
        return Arrays.asList("statics", "excludes");
    }


    @Override
    public GatewayFilter apply(Config config) {
        return (exchange, chain) -> {


            if (checkStaticResource(config.isStatics(), exchange.getRequest())) {
                return chain.filter(exchange);
            }

            exchange.getAttributes().put(START_TIME, System.currentTimeMillis());
            return chain.filter(exchange).then(Mono.fromRunnable(() -> responseCallBack(config, exchange)));

        };
    }


    public static class Config {

        //是否过滤静态资源 默认过滤
        private boolean statics = true;

        //排除请求后缀
        private String excludes;

        public boolean isStatics() {
            return statics;
        }

        public void setStatics(boolean statics) {
            this.statics = statics;
        }

        public String getExcludes() {
            return excludes;
        }

        public void setExcludes(String excludes) {
            this.excludes = excludes;
        }
    }

    /**
     * 记录日志信息
     *
     * @param config
     * @param exchange
     */
    @Override
    protected void responseCallBack(Config config, ServerWebExchange exchange) {
        Long startTime = exchange.getAttribute(START_TIME);
        Long executeTime = null;
        if (startTime != null) {
            executeTime = (System.currentTimeMillis() - startTime);
        }
        ServerHttpRequest request = exchange.getRequest();
        ServerHttpResponse response = exchange.getResponse();
        String userAgent = request.getHeaders().getFirst("User-Agent");

        UserAgent ua = UserAgentUtil.parse(userAgent);

        Map param = new HashMap(11);
        Route route = exchange.getAttribute(ServerWebExchangeUtils.GATEWAY_ROUTE_ATTR);
        param.put("logRoute",route.getId());
        param.put("logRequestId", request.getId());
        param.put("logTime", startTime);
        param.put("logIp", request.getRemoteAddress().getAddress().getHostAddress());
        param.put("logSystem", ua.getPlatform().toString());
        param.put("logBrower", ua.getBrowser().toString());
        param.put("logVersion", ua.getVersion());
        param.put("logMobile", ua.isMobile() ? 1 : 0);
        param.put("logUrl", request.getURI().toString());
        param.put("logMethod", request.getMethod().toString());
        param.put("logStatus", response.getStatusCode().value());
        param.put("logMessage", response.getStatusCode().getReasonPhrase());
        param.put("logTook", executeTime);
        auditLogService.auditLog(param);

    }

}
